package com.my.study.excel.export;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.WriteWorkbook;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

/**
 * excel数据导入导出
 * 支持大数据量导入导出
 *
 */
@Slf4j
public abstract class BaseExcelExportService implements ExcelExportService {

    @Override
    public abstract long getTotalDataNum(Map<String, String> map);

    @Override
    public abstract long getSheetRowNum();

    @Override
    public abstract long writeNum();

    @Override
    public abstract List<List<String>> setTableHead();

    @Override
    public abstract List<List<String>> queryWriteData(Map<String, String> map);

    protected void exportData(HttpServletResponse response, Map<String, String> map, String fileName) {
        try (OutputStream outputStream = response.getOutputStream()) {
            // 获取输出流
            WriteWorkbook writeWorkbook = new WriteWorkbook();
            writeWorkbook.setOutputStream(outputStream);
            writeWorkbook.setExcelType(ExcelTypeEnum.XLSX);
            ExcelWriter writer = new ExcelWriter(writeWorkbook);
            // 设置导出的excel表头
            WriteTable table = new WriteTable();
            table.setUseDefaultStyle(true);
            table.setHead(setTableHead());
            // 计算相关参数
            long totalRowCount = getTotalDataNum(map);
            long perSheetRowCount = getSheetRowNum();
            long pageSize = writeNum();
            int sheetCount = Math.toIntExact(totalRowCount % perSheetRowCount == 0 ?
                    (totalRowCount / perSheetRowCount) : (totalRowCount / perSheetRowCount + 1));
            int previousSheetWriteCount = Math.toIntExact(perSheetRowCount / pageSize);
            int lastSheetWriteCount = Math.toIntExact(totalRowCount % perSheetRowCount == 0 ?
                    previousSheetWriteCount :
                    (totalRowCount % perSheetRowCount % pageSize == 0 ?
                            totalRowCount % perSheetRowCount / pageSize : (totalRowCount % perSheetRowCount / pageSize + 1)));
            // 数据写入
            for (int i = 0; i < sheetCount; i++) {
                // 创建SHEET
                WriteSheet sheet = new WriteSheet();
                sheet.setSheetName(fileName + i);
                sheet.setSheetNo(i);
                table.setTableNo(i);
                // 写数据
                for (int j = 0; j < (i != sheetCount - 1 ? previousSheetWriteCount : lastSheetWriteCount); j++) {
                    int curPage = j + 1 + previousSheetWriteCount * i;
                    map.put("curPage", String.valueOf(curPage));
                    map.put("pageSize", String.valueOf(pageSize));
                    // 获取数据
                    List<List<String>> dataList = queryWriteData(map);
                    writer.write(dataList, sheet, table);
                }
            }
            // 下载EXCEL
            response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes("gb2312"), "ISO-8859-1") + ".xlsx");
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            writer.finish();
            outputStream.flush();
        } catch (IOException e) {
            log.error("excel导出失败:{}", e.getMessage(), e);
        }
    }
}
